package org.mbds.android.sismapp.view;

import java.util.ArrayList;

import org.mbds.android.chart.LineChartAttributes;
import org.mbds.android.chart.PathOnChart;
import org.mbds.android.geometry.PointFloat;


import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.RectF;
import android.graphics.Matrix;

/**
 * 
 * @author vlwb5512
 *
 */
public class SensorLinesChartView extends ChartView {
	private float no_of_x_positive_unit;
	private float no_of_y_positive_unit;
	private float no_of_x_negative_unit;
	private float no_of_y_negative_unit;
	private float x_unit_length;
	private float y_unit_length;
	private float x_translate_factor;
	private float y_translate_factor;
	private ArrayList<PathOnChart> paths;
	private LineChartAttributes lineChartAttributes;
	private ArrayList<float[]> orientations;
	private ArrayList<float[]> rotations;
	private double minimum_x = 0;
	private double maximum_x = 0;
	private double minimum_y = 0;
	private double maximum_y = 0;
	private double[] min = new double[4];
	private double[] max = new double[4];
	private double[] sum = new double[4];
	private double[] moy = new double[4];

	public final static float ORIENTATION_COEFF = 0.75f;

	private Bitmap mobile;

	private float centerx;
	private float centery;
	private float centerz;

	public static final int DEVICE_CENTER_Z = -150;

	// Mobile size
	private final float sx = 45; // size x
	private final float sy = 100; // size y
	private final float sz = 15; // size z

	// Display size
	private final float dx = 42; // size x
	private final float dy1 = 106; // size y
	private final float dy2 = -45;

	/** Contains the grid model of the phone. */
	private final float[][] phone = {
			// bottom shape
			{ sx, sy, -sz }, { -sx, sy, -sz },
			{ -sx, sy, -sz },
			{ -sx, -sy, -sz },
			{ -sx, -sy, -sz },
			{ sx, -sy, -sz },
			{ sx, -sy, -sz },
			{ sx, sy, -sz },
			// top shape
			{ sx, sy, sz }, { -sx, sy, sz }, { -sx, sy, sz }, { -sx, -sy, sz },
			{ -sx, -sy, sz },
			{ sx, -sy, sz },
			{ sx, -sy, sz },
			{ sx, sy, sz },
			// connectint top and bottom
			{ sx, sy, -sz }, { sx, sy, sz }, { -sx, sy, -sz }, { -sx, sy, sz },
			{ -sx, -sy, -sz }, { -sx, -sy, sz },
			{ sx, -sy, -sz },
			{ sx, -sy, sz },
			// display
			{ dx, dy1, sz }, { -dx, dy1, sz }, { -dx, dy1, sz },
			{ -dx, dy2, sz }, { -dx, dy2, sz }, { dx, dy2, sz },
			{ dx, dy2, sz }, { dx, dy1, sz }, 
	};


	public SensorLinesChartView(Activity activity, ArrayList<PathOnChart> paths,
			LineChartAttributes lineChartAttributes, ArrayList<float[]> orientations, ArrayList<float[]> rotations) {
		super(activity);
//		mobile = BitmapFactory.decodeResource(getResources(), R.drawable.phone);
		initDisplaySize();
		centerx = display_width/2;
		centery = display_height/2;
		centerz = DEVICE_CENTER_Z;
		this.lineChartAttributes = lineChartAttributes;
		configurePaths(paths, orientations, rotations, true);
	}

	public ArrayList<PathOnChart> configurePaths(ArrayList<PathOnChart> paths, 
			ArrayList<float[]> orientations, ArrayList<float[]> rotations, boolean init) {
		this.orientations = orientations;
		this.rotations = rotations;
		double min_x = 0;
		double max_x = 0;
		double min_y = 0;
		double max_y = 0;
		ArrayList<PathOnChart> paths_configured = paths;
		for (int i=0; i<paths_configured.size();i++) {
			PathOnChart pathOnChart = paths_configured.get(i);
			ArrayList<PointFloat> points = pathOnChart.points;
			if (i<4) {
				min[i]=0;
				max[i]=0;
				moy[i]=0;
				sum[i]=0;
			}
			if (points.size()>0) {
				for (PointFloat pointOnChart : points) {
	
					if (pointOnChart.y < min[i])
						min[i] = pointOnChart.y;
					if (pointOnChart.y > max[i])
						max[i] = pointOnChart.y;
					sum[i] += pointOnChart.y;
					if (pointOnChart.x < min_x)
						min_x = pointOnChart.x;
					if (pointOnChart.y < min_y)
						min_y = pointOnChart.y;
					if (pointOnChart.x > max_x)
						max_x = pointOnChart.x;
					if (pointOnChart.y > max_y)
						max_y = pointOnChart.y;
				}
				if (i<3) 
					moy[i] = sum[i]/points.size();
			}
		}
		if (init) {
			minimum_x = min_x;
			minimum_y = min_y;
			maximum_x = max_x;
			maximum_y = max_y;
		} else {
			if (min_x<minimum_x)
				minimum_x=min_x;
			if (min_y<minimum_y)
				minimum_y=min_y;
			if (max_x>maximum_x)
				maximum_x=max_x;
			if (max_y>maximum_y)
				maximum_y=max_y;
		}
		no_of_x_negative_unit = (float) Math.abs(minimum_x);
		no_of_x_positive_unit = (float) Math.abs(maximum_x);
		no_of_y_negative_unit = (float) Math.abs(minimum_y);
		no_of_y_positive_unit = (float) Math.abs(maximum_y);
		x_unit_length = (float) (chart_width / (no_of_x_negative_unit + no_of_x_positive_unit));
		y_unit_length = (float) (chart_height / (no_of_y_negative_unit + no_of_y_positive_unit));

		y_translate_factor = display_height - offset_bottom;
		x_translate_factor = ((float)  no_of_x_negative_unit * x_unit_length)
				+ offset_left;
		y_translate_factor = display_height
				- ((float) no_of_y_negative_unit * y_unit_length) - offset_bottom;
		for (PathOnChart pathOnChart : paths_configured) {
			ArrayList<PointFloat> points = pathOnChart.points;
			for (PointFloat pointOnChart : points) {
				pointOnChart.x = x_translate_factor
						+ pointOnChart.x * x_unit_length;
				pointOnChart.y = y_translate_factor
						- pointOnChart.y * y_unit_length;
			}
		}
		this.paths = paths; 
		return paths;
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		canvas.drawColor(Color.WHITE);
		if (lineChartAttributes.getBackground() != null)
			canvas.drawBitmap(lineChartAttributes.getBackground(), 0, 0, paint);
		if (lineChartAttributes.isGridVisible())
			drawGrid(canvas);
		drawAxis(canvas);
		drawAxisNames(canvas);
//		if (Properties.showPoints)
//			drawPoints(canvas);
//		if (Properties.showLines)
			drawPhaths(canvas);
//		if (Properties.showPhoneOrientation || Properties.showPhoneRotation)
//			drawPhone(canvas);
	}

	private void drawPhone(Canvas canvas) {
		int size =orientations.size();
		if (size>0) {
			float[] orientation = orientations.get(size-1);
			if (orientation==null)
				return;
			float yaw = (float) Math.toDegrees(orientation[0]);
			float pitch = (float) Math.toDegrees(orientation[1]);
			float roll = (float) Math.toDegrees(orientation[2]);
			
			paint.setColor(Color.BLACK);
			String st = (yaw+"").length()>5?(yaw+"").substring(0, 6):yaw+"";
			canvas.drawText("Yaw: "+st, (float)centerx+200, (float)(centery-paint.getTextSize()-5+70), paint);
			st = (pitch+"").length()>5?(pitch+"").substring(0, 6):pitch+"";
			canvas.drawText("Pitch: "+st, (float)centerx+200, (float)centery+70, paint);
			st = (roll+"").length()>5?(roll+"").substring(0, 6):roll+"";
			canvas.drawText("Roll: "+st, (float)centerx+200, (float)(centery+paint.getTextSize()+5+70), paint);

//			if (Properties.showPhoneOrientation) {
//				// Yaw
//				Matrix matrix = new Matrix(); 
//				matrix.preTranslate(centerx-mobile.getWidth()/2, centery-mobile.getHeight()/2);
//				matrix.setRotate(yaw*ORIENTATION_COEFF);
//				Bitmap bmp = Bitmap.createBitmap(mobile, 0, 0, mobile.getWidth(), 
//						mobile.getHeight(), matrix, true);
//				paint.setAlpha(100);
//				canvas.drawBitmap(bmp, centerx-bmp.getWidth()/2,centery-bmp.getHeight()/2, paint);
//				paint.setAlpha(0);
//			}
//			if (Properties.showPhoneRotation) {
//				//
//				for (int i = 0; i < phone.length; i += 2) {
//					if (i == 0) {
//						paint.setColor(Color.GREEN);
//					}
//					if (i == 24) {
//						paint.setColor(Color.BLUE);
//					}
//					Vector v1 = new Vector(phone[i]);
//					Vector v2 = new Vector(phone[i + 1]);
//					v1.rollpitchyaw(roll, pitch, yaw);
//					v2.rollpitchyaw(roll, pitch, yaw);
//					Path path = new Path();
//					super.paint.setStyle(Paint.Style.STROKE);
//					path.moveTo((float) (centerx + v1.x * centerz
//							/ (centerz - v1.y)), (float) (centery - v1.z * centerz
//							/ (centerz - v1.y)));
//					path.lineTo((float) (centerx + v2.x * centerz
//							/ (centerz - v2.y)), (float) (centery - v2.z * centerz
//							/ (centerz - v2.y)));
//					path.close();
//					canvas.drawPath(path, paint);
//				}
//			}
		}
	}
	
	private void drawPhaths(Canvas canvas) {
		for (int i = 0; i<paths.size();i++) {
//			if (i==0 && !Properties.showX)
//				continue;
//			if (i==1 && !Properties.showY)
//				continue;
//			if (i==2 && !Properties.showZ)
//				continue;
//			if (i==3 && !Properties.showComputedData)
//				continue;
			PathOnChart pathOnChart = paths.get(i);
			if (pathOnChart.points.size()>0) {
				paint.setColor(Color.parseColor(pathOnChart.attributes.pointColor));
				Path path = new Path();
				PointFloat p1 = pathOnChart.points.get(0);
				path.moveTo(p1.x, p1.y);
				for (PointFloat point : pathOnChart.points) {
					path.quadTo(p1.x, p1.y, point.x, point.y);
					p1 = point;
					path.lineTo(p1.x, p1.y);
					super.paint.setColor(Color
							.parseColor(pathOnChart.attributes.pathColor));
					super.paint
							.setStrokeWidth(pathOnChart.attributes.strokeWidthOfPath);
					super.paint.setStyle(Paint.Style.STROKE);
					canvas.drawPath(path, paint);
				}
			}
		}
	}

	private void drawAxisNames(Canvas canvas) {
		paint.setColor(Color.parseColor(lineChartAttributes.getAxisNameColor()));
		paint.setStrokeWidth(lineChartAttributes.getAxisStrokeWidth());
		Path path = new Path();
		RectF rect = new RectF(xbl - offset_left * 0.50f, ybl, xtl
				- offset_left * 0.50f, ytl);
		path.addRect(rect, Direction.CCW);
		canvas.drawTextOnPath(lineChartAttributes.getY_unit_name(), path, 0, 0,
				paint);
		path = new Path();
		rect = new RectF(xbl, ybl + offset_bottom * 0.50f, xbr, ybr
				+ offset_bottom * 0.50f);
		path.addRect(rect, Direction.CW);
		canvas.drawTextOnPath(lineChartAttributes.getX_unit_name(), path, 0, 0,
				paint);
		paint.setColor(Color.parseColor(paths.get(0).attributes.pathColor));
		canvas.drawText("X", xbl - offset_left * 0.50f, xtl-30, paint);
		paint.setColor(Color.BLACK);
		String st = "";
//		if (Properties.showX) {
			st = (min[0]+"").length()>5?(min[0]+"").substring(0, 6):min[0]+"";
			canvas.drawText("Min x: "+st, (float)centerx/2-100, xtl-30, paint);
			st = (max[0]+"").length()>5?(max[0]+"").substring(0, 6):max[0]+"";
			canvas.drawText("Max x: "+st, (float)centerx/2+50, xtl-30, paint);
			st = (moy[0]+"").length()>5?(moy[0]+"").substring(0, 6):moy[0]+"";
			canvas.drawText("Moy x: "+st, (float)centerx/2+200, xtl-30, paint);
			paint.setColor(Color.parseColor(paths.get(1).attributes.pathColor));
//		}
//		if (Properties.showY) {
			canvas.drawText("Y", xbl - offset_left * 0.50f, xtl-30+paint.getTextSize()+5, paint);
			paint.setColor(Color.BLACK);
			st = (min[1]+"").length()>5?(min[1]+"").substring(0, 6):min[1]+"";
			canvas.drawText("Min y: "+st, (float)centerx/2-100, xtl-30+paint.getTextSize()+5, paint);
			st = (max[1]+"").length()>5?(max[1]+"").substring(0, 6):max[1]+"";
			canvas.drawText("Max y: "+st, (float)centerx/2+50, xtl-30+paint.getTextSize()+5, paint);
			st = (moy[1]+"").length()>5?(moy[1]+"").substring(0, 6):moy[1]+"";
			canvas.drawText("Moy y: "+st, (float)centerx/2+200, xtl-30+paint.getTextSize()+5, paint);
			paint.setColor(Color.parseColor(paths.get(2).attributes.pathColor));
//		}
//		if (Properties.showZ) {
			canvas.drawText("Z", xbl - offset_left * 0.50f, xtl-30+(paint.getTextSize()+5)*2, paint);
			paint.setColor(Color.BLACK);
			st = (min[2]+"").length()>5?(min[2]+"").substring(0, 6):min[2]+"";
			canvas.drawText("Min z: "+st, (float)centerx/2-100, xtl-30+(paint.getTextSize()+5)*2, paint);
			st = (max[2]+"").length()>5?(max[2]+"").substring(0, 6):max[2]+"";
			canvas.drawText("Max z: "+st, (float)centerx/2+50, xtl-30+(paint.getTextSize()+5)*2, paint);
			st = (moy[2]+"").length()>5?(moy[2]+"").substring(0, 6):moy[2]+"";
			canvas.drawText("Moy z: "+st, (float)centerx/2+200, xtl-30+(paint.getTextSize()+5)*2, paint);
//		}
		paint.setColor(Color.parseColor(lineChartAttributes.getAxisNameColor()));
	}

	private void drawPoints(Canvas canvas) {
		for (int i = 0; i<paths.size();i++) {
//			if (i==0 && !Properties.showX)
//				continue;
//			if (i==1 && !Properties.showY)
//				continue;
//			if (i==2 && !Properties.showZ)
//				continue;
//			if (i==3 && !Properties.showComputedData)
//				continue;
			PathOnChart path = paths.get(i);
			paint.setColor(Color.parseColor(path.attributes.pathColor));
			for (PointFloat point : path.points) {
				canvas.drawCircle((float) point.x, (float) point.y,
						path.attributes.radiusOfPoints, paint);
			}
		}
	}

	private void drawAxis(Canvas canvas) {
		paint.setColor(Color.parseColor(lineChartAttributes.getAxisColor()));
		paint.setStrokeWidth(lineChartAttributes.getAxisStrokeWidth());
		// y
		canvas.drawLine(
				(float) (xtl + (no_of_x_negative_unit * x_unit_length)), ytl,
				(float) (xbl + (no_of_x_negative_unit * x_unit_length)), ybl,
				paint);
		// x
		canvas.drawLine(xtl,
				(float) (ytl + (no_of_y_positive_unit * y_unit_length)), xtr,
				(float) (ytr + (no_of_y_positive_unit * y_unit_length)), paint);
	}

	private void drawGrid(Canvas canvas) {
		paint.setColor(Color.parseColor(lineChartAttributes.getAxisNameColor()));
		float max_stroke_width = lineChartAttributes.getGridStrokeWidth();
		float gridStrokeWidth_x = max_stroke_width;
		float gridStrokeWidth_y = max_stroke_width;
		gridStrokeWidth_x = (float) (10 / (no_of_x_negative_unit + no_of_x_positive_unit));
		gridStrokeWidth_y = (float) (10 / (no_of_y_negative_unit + no_of_y_positive_unit));
		gridStrokeWidth_x = (gridStrokeWidth_x > max_stroke_width) ? max_stroke_width
				: gridStrokeWidth_x;
		gridStrokeWidth_y = (gridStrokeWidth_y > max_stroke_width) ? max_stroke_width
				: gridStrokeWidth_y;
		paint.setStrokeWidth(gridStrokeWidth_x);
		for (int i = 0; i < Math.round(no_of_x_negative_unit + no_of_x_positive_unit); i++) {
			canvas.drawText (i+"", xtl + (i * x_unit_length), ybl+15, paint); 
			canvas.drawLine(xtl + (i * x_unit_length), ytl, xbl
					+ (i * x_unit_length), ybl, paint);
		}
		paint.setStrokeWidth(gridStrokeWidth_y);
		for (int i = 0; i < Math.round(no_of_y_negative_unit + no_of_y_positive_unit); i++) {
			long j = Math.round(no_of_y_positive_unit)-i;
			canvas.drawText (j+"", xtl-15, ytl + (i * y_unit_length), paint); 
			canvas.drawLine(xtl, ytl + (i * y_unit_length), xtr, ytr
					+ (i * y_unit_length), paint);
		}
	}
}